package com.yuanlang.services.fasthdsf.impl;

import com.yuanlang.common.ResultMap;
import com.yuanlang.common.util.SysUtils;
import com.yuanlang.common.util.SystemConfig;
import com.yuanlang.common.util.SystemMsgCode;
import com.yuanlang.facade.model.system.TsFile;
import com.yuanlang.services.fasthdsf.FileTransferService;
import com.yuanlang.services.fasthdsf.core.FastDFSFile;
import com.yuanlang.services.fasthdsf.core.FileManager;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

@Service(value = "fileTransferService")
public class FileTransferServiceImpl implements FileTransferService {

    private static Logger logger = LoggerFactory.getLogger(FileTransferServiceImpl.class);

    @Value("${pic.MaxFileSize}") // 图片最大

    private Integer picMaxFileSize;

    @Autowired
    @Qualifier("fileManager")
    private FileManager fileManager;

    @Autowired(required = false)
    //@Qualifier("systemConfig")
    private SystemConfig systemConfig;


    public Integer getPicMaxFileSize() {
        return picMaxFileSize;
    }

    @Override
    public ResultMap fileUpload(String fileName, String fileBase64) {
        ResultMap result = new ResultMap();
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] resultImg = decoder.decodeBuffer(fileBase64.split(",")[1]);
            for (int i = 0; i < resultImg.length; ++i) {
                if (resultImg[i] < 0) {// 调整异常数据
                    resultImg[i] += 256;
                }
            }
            if (resultImg.length > picMaxFileSize) {
                result.setCode(SystemMsgCode.DFS_EXCEED_MAX_FILESIZE.getResultCode());
                result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_EXCEED_MAX_FILESIZE.getResultCode()));
                return result;
            }
            List<String> paths = new ArrayList<String>();
            String fName = SysUtils.nullString(fileName);
            int index = fName.lastIndexOf(".");
            String extName = "";
            if (index >= 0 && index < fName.length() - 1) {
                extName = fName.substring(index + 1);
                fName = fName.substring(0, index);
            }
            FastDFSFile fdfsFile = new FastDFSFile(fName, resultImg, extName);

            String fileAbsolutePath = fileManager.upload(fdfsFile);
            result.setCode(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode()));
            if (fileAbsolutePath == null) return result;
            paths.add(fileAbsolutePath);
            result.setCode(SystemMsgCode.DFS_UPLOAD_SUCCESS.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_SUCCESS.getResultCode()));
            result.setData(paths);
            return result;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(), e);
            logger.error(e.getMessage(), e);
            result.setCode(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode()) + e.getLocalizedMessage());
            return result;
        }
    }


    @Override
    public ResultMap fileUpload(MultipartFile file) {
        ResultMap result = new ResultMap();
        TsFile tsFile = new TsFile();
        try {
                String fName = file.getOriginalFilename();
                int index = fName.lastIndexOf(".");
                String extName = "";
                if (index >= 0 && index < fName.length() - 1) {
                    extName = fName.substring(index + 1);
                    fName = fName.substring(0, index);
                }

                FastDFSFile fdfsFile = new FastDFSFile(fName, file.getBytes(), extName);
                String fileAbsolutePath = fileManager.upload(fdfsFile);
                result.setCode(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode());
                result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode()));

                tsFile.setFileName(fName);
                tsFile.setFilePath(fileAbsolutePath);
                tsFile.setFileType(extName);
                tsFile.setFileSize(file.getSize());

                if (fileAbsolutePath == null) return result;
                result.setCode(SystemMsgCode.DFS_UPLOAD_SUCCESS.getResultCode());
                result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_SUCCESS.getResultCode()));
                result.setData(tsFile);
            return result;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            result.setCode(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode()));
            return result;
        }
    }

    /**
     * @param files 批量上传文件
     * @return
     */
    @Override
    public ResultMap fileUpload(MultipartFile[] files) {
        ResultMap result = new ResultMap();
        // TODO Auto-generated method stub
        try {
            List<String> paths = new ArrayList<String>();
            for (MultipartFile file : files) {
                /*if (file.getSize() > picMaxFileSize) {
                    result.setCode(SystemMsgCode.DFS_EXCEED_MAX_FILESIZE.getResultCode());
                    result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_EXCEED_MAX_FILESIZE.getResultCode()));
                    return result;
                }*/
                String fName = file.getOriginalFilename();
                int index = fName.lastIndexOf(".");
                String extName = "";
                if (index >= 0 && index < fName.length() - 1) {
                    extName = fName.substring(index + 1);
                    fName = fName.substring(0, index);
                }
                FastDFSFile fdfsFile = new FastDFSFile(fName, file.getBytes(), extName);
                String fileAbsolutePath = fileManager.upload(fdfsFile);
                result.setCode(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode());
                result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode()));
                if (fileAbsolutePath == null) return result;
                paths.add(fileAbsolutePath);
            }
            result.setCode(SystemMsgCode.DFS_UPLOAD_SUCCESS.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_SUCCESS.getResultCode()));
            result.setData(paths);
            return result;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(), e);
            result.setCode(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode()));
            return result;
        }
    }

    @Override
    public ResultMap fileUpload(String localFileName) {
        ResultMap result = new ResultMap();
        try {
            String fileAbsolutePath = fileManager.upload(localFileName);
            List<String> paths = new ArrayList<String>();
            result.setCode(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode()));
            if (fileAbsolutePath == null) return result;
            paths.add(fileAbsolutePath);
            result.setCode(SystemMsgCode.DFS_UPLOAD_SUCCESS.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_SUCCESS.getResultCode()));
            result.setData(paths);
            return result;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            result.setCode(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_UPLOAD_FAILED.getResultCode()) + e.getLocalizedMessage());
            return result;
        }
    }

    @Override
    public void deleteFile(String remoteFileNameWithGroupName) {
        try {
            SplitFileNameAdnGroupName splitFileNameAdnGroupName = new SplitFileNameAdnGroupName(remoteFileNameWithGroupName).invoke();
            if (splitFileNameAdnGroupName.is()) return;
            String groupName = splitFileNameAdnGroupName.getGroupName();
            String remoteFileName = splitFileNameAdnGroupName.getRemoteFileName();
            fileManager.deleteFile(groupName, remoteFileName);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }


    /**
     * @param remoteFileNameWithGroupName
     * @param savePath
     * @return
     */
    @Override
    public ResultMap download(String remoteFileNameWithGroupName, String savePath) {
        ResultMap result = new ResultMap();
        SplitFileNameAdnGroupName splitFileNameAdnGroupName = new SplitFileNameAdnGroupName(remoteFileNameWithGroupName).invoke();

        if (splitFileNameAdnGroupName.is()) {
            result.setCode(SystemMsgCode.DFS_DOWNLOAD_FAILED.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_DOWNLOAD_FAILED.getResultCode()));
            return result;
        }
        File dir = new File(savePath);
        if (!dir.exists() && !dir.isDirectory())
            dir.mkdirs();
        String groupName = splitFileNameAdnGroupName.getGroupName();
        String remoteFileName = splitFileNameAdnGroupName.getRemoteFileName();
        return fileManager.download(groupName, remoteFileName, savePath);
    }

    /**
     * @param remoteFileNameWithGroupName
     */
    @Override
    public ResultMap downloadAsBytes(String remoteFileNameWithGroupName) {
        ResultMap result = new ResultMap();
        SplitFileNameAdnGroupName splitFileNameAdnGroupName = new SplitFileNameAdnGroupName(remoteFileNameWithGroupName).invoke();
        if (splitFileNameAdnGroupName.is()) {
            result.setCode(SystemMsgCode.DFS_DOWNLOAD_FAILED.getResultCode());
            result.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_DOWNLOAD_FAILED.getResultCode()));
            //return OperationResult.failedResult();
            return result;
        }
        String groupName = splitFileNameAdnGroupName.getGroupName();
        String remoteFileName = splitFileNameAdnGroupName.getRemoteFileName();
        return fileManager.downloadAsBytes(groupName, remoteFileName);
    }

    @Override
    public char getPathSeparator() {
        return fileManager.SEPARATOR;
    }

    @Override
    public void outFileStream(String fileURL, Boolean kjbDFS, HttpServletResponse response) {
        String file = fileURL;
        if (kjbDFS)
            file = systemConfig.getFileServerUrl() + fileURL;
        try {
            //http://114.215.221.123/ueditor/jsp/upload/file/20170413/1492017493544030070.pdf
            // 纯下载方式
            response.setContentType("application/x-msdownload");
            response.setHeader("Content-Disposition", "attachment;filename=" + file.substring(file.lastIndexOf("/" + 1), file.length()));
            URL url = new URL(file);
            URLConnection conn = url.openConnection();
            InputStream fileInputStream = conn.getInputStream();
            OutputStream outputStream = response.getOutputStream();
            IOUtils.write(IOUtils.toByteArray(fileInputStream), outputStream);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    private class SplitFileNameAdnGroupName {
        private boolean myResult;
        private String remoteFileNameWithGroupName;
        private String groupName;
        private String remoteFileName;

        public SplitFileNameAdnGroupName(String remoteFileNameWithGroupName) {
            this.remoteFileNameWithGroupName = remoteFileNameWithGroupName;
        }

        boolean is() {
            return myResult;
        }

        public String getGroupName() {
            return groupName;
        }

        public String getRemoteFileName() {
            return remoteFileName;
        }

        public SplitFileNameAdnGroupName invoke() {
            int pos = remoteFileNameWithGroupName.indexOf(String.valueOf(getPathSeparator()));
            if (pos < 1) {
                myResult = true;
                return this;
            }
            groupName = remoteFileNameWithGroupName.substring(0, pos);
            remoteFileName = remoteFileNameWithGroupName.substring(pos + 1);
            myResult = false;
            return this;
        }
    }
}
